package edu.ccut.saturn.component.loader;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.osgi.framework.Bundle;

import edu.ccut.saturn.component.ILogger;
import edu.ccut.saturn.component.IMuneItemInfo;
import edu.ccut.saturn.component.SaturnComponentException;
import edu.ccut.saturn.component.SaturnLoggerManager;
import edu.ccut.saturn.component.impl.SaturnMenuItemInfo;
import edu.ccut.saturn.component.xml.Dom4jUtils;

/**
 * 菜单配置文件的加载类
 * 
 * @author 温建
 * 
 * @version 1.0 2008.9.03
 * 
 * @see IMuneItemInfo
 * 
 */
public class MenuInfoLoader {

	private static final String LOGGER_KEY_LOAD_BUNDLE = SaturnLoggerManager.LOGGER_KEY_LOAD_BUNDLE;

	protected static ILogger logger = SaturnLoggerManager.getInstance()
			.getSaturnLogger(LOGGER_KEY_LOAD_BUNDLE);

	private static final String KEY_MENU_MENUITEM = "menuItem";

	private static final String KEY_MENUITEM_LABEL = "label";

	private static final String KEY_MENUITEM_PATH = "path";

	private static final String KEY_MENUITEM_ID = "id";

	private static final String KEY_MENUITEM_ORDER = "order";

	private static final String KEY_MENUITEM_PARENTID = "parentId";

	/**
	 * 加载菜单配置文件，首先指定根节点为当前加载节点，先加载当前结点内部子节点的菜单描述信息，再加载当前结点的菜单描述信息；加载每个菜单描述信息都重复上面操作；
	 * 最后加载根节点的菜单描述信息后，整个加载过程结束。
	 * <p>菜单项通过id属性进行唯一标识，parentId是对id的引用表示父菜单的id号。id需要在前面加bundle名称+“::”的前缀。
	 * 
	 * @param bundle
	 * @param url
	 * @return
	 * @throws SaturnComponentException
	 */
	public static List<IMuneItemInfo> loadSaturnMenuItemInfos(Bundle bundle,
			URL url) throws SaturnComponentException {

		InputStream in = null;

		try {
			logger.debug("MENU CONFIG START \"" + url + "\"");
			in = url.openStream();
			return loadSaturnMenuItemInfos(bundle, in);

		} catch (IOException e) {
			logger.error(
					"Found IOException! load menu config file failed in bundle [key="
							+ bundle.getSymbolicName() + "]", e);

			throw new SaturnComponentException(
					"load menu config file failed in bundle [key="
							+ bundle.getSymbolicName() + "]", e);

		} catch (Exception e) {
			throw new SaturnComponentException(
					"load menu config file failed in bundle [key="
							+ bundle.getSymbolicName() + "]", e);

		} finally {

			try {

				if (in != null) {
					in.close();
				}

			} catch (IOException e) {
				logger.error("menu config file input stream close error!", e);
			}
			logger.debug("MENU CONFIG END");
			logger.debug("");
		}
	}

	public static List<IMuneItemInfo> loadSaturnMenuItemInfos(Bundle bundle,
			InputStream in) throws SaturnComponentException {

		Document document = Dom4jUtils.getDocment(in);
		Element root = document.getRootElement();
		List<IMuneItemInfo> menuItems = new ArrayList<IMuneItemInfo>();

		if (!root.elements().isEmpty()) {
			loadMenuItemInfos(bundle, root, menuItems);
		}
		return menuItems;
	}

	@SuppressWarnings("unchecked")
	private static void loadMenuItemInfos(Bundle bundle, Element menu,
			List<IMuneItemInfo> menuItems) {

		List<Element> elements = menu.elements(KEY_MENU_MENUITEM);

		if (elements != null && elements.size() > 0) {

			for (Element menuItem : elements) {
				loadMenuItemInfos(bundle, menuItem, menuItems);
			}
		}
		String id = menu.attributeValue(KEY_MENUITEM_ID);
		String label = menu.attributeValue(KEY_MENUITEM_LABEL);
		String path = menu.attributeValue(KEY_MENUITEM_PATH);
		String order = menu.attributeValue(KEY_MENUITEM_ORDER);
		String parentId = menu.attributeValue(KEY_MENUITEM_PARENTID);

		if (id == null) {
			return;

		} else {
			id = id.trim();

			if (id.indexOf("::") < 0) {
				id = bundle.getSymbolicName() + "::" + id;
			}
			label = label.trim();
			path = path.trim();
			order = order.trim();
			parentId = parentId.trim();

			if (!parentId.equals("") && parentId.indexOf("::") < 0) {
				parentId = bundle.getSymbolicName() + "::" + parentId;
			}
		}
		SaturnMenuItemInfo saturnMenuItemInfo = new SaturnMenuItemInfo(label,
				path, id, order, parentId, null);

		menuItems.add(saturnMenuItemInfo);
	}
}
